using System;
using System.Collections.Generic;
using System.Text;

namespace Derm.Render
{
	/// <summary>
	/// Font styles.
	/// </summary>
	[Flags]
	public enum FontStyle
	{
		/// <summary>
		/// No styles.
		/// </summary>
		None =		0x0000,
		/// <summary>
		/// Bold font style.
		/// </summary>
		Bold =		0x0001,
		/// <summary>
		/// Italic font style.
		/// </summary>
		Italic =	0x0002
	}

	/// <summary>
	/// 
	/// </summary>
	[RenderObjectProgram("FontShader")]
	public class FontObject : RenderObject
	{
		#region Constructors

		/// <summary>
		/// 
		/// </summary>
		public FontObject(string family, uint size, FontStyle styles)
		{
			VertexArrayObject vao = new VertexArrayObject();

			// A simple unit quad
			ArrayBufferObject<Vertex2f> vertices = new ArrayBufferObject<Vertex2f>(BufferObject.Hint.StaticCpuDraw);
			vertices.Define(new Vertex2f[]
								{
									new Vertex2f(0.0f, 0.0f), new Vertex2f(1.0f, 0.0f), new Vertex2f(0.0f, 1.0f), new Vertex2f(1.0f, 1.0f)
								});
			vao.SetArray("ds_VertexPosition", "FontVertexShaderInputs", vertices);
			vao.SetElementArray(Primitive.TriangleStrip);
			VertexArrays.AddVertexArray(vao);

			mFontResource = FontResource.Create(family, size, styles);
		}

		#endregion

		#region Font Resources

		/// <summary>
		/// Resources of this FontObject.
		/// </summary>
		private readonly FontResource mFontResource;

		#endregion

		#region Text String

		public void SetText(string format, params object[] args)
		{
			mFontText = String.Format(format, args);
		}

		/// <summary>
		/// Currently font text.
		/// </summary>
		private string mFontText = String.Empty;

		#endregion

		#region Shader Uniform State

		/// <summary>
		/// Font texture.
		/// </summary>
		[RenderObjectUniform("ds_FontTexture")]
		public Texture2d FontTexture { get { return (mFontResource.FontTexture); } }

		#endregion

		#region RenderObject Overrides

		/// <summary>
		/// Actually create this RenderResource resources.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="RenderContext"/> used for allocating resources.
		/// </param>
		protected override void CreateObject(RenderContext ctx)
		{
			// Create font resource
			mFontResource.Create(ctx);
			// Base implementation
			base.CreateObject(ctx);
		}

		/// <summary>
		/// Render this object.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="RenderContext"/> used for rendering.
		/// </param>
		protected override void RenderThis(RenderContext ctx)
		{
			float x = 0.0f;

			foreach (char c in mFontText) {
				FontGlyphImage.GlyphCoord glyphCoord = mFontResource.FontGlyphInfo.GetGlyphCoord(c);

				// Quad position
				RenderProgram.SetUniform(ctx, "ds_FontPositionOffset", x, 0.0f);
				RenderProgram.SetUniform(ctx, "ds_FontPositionScale", glyphCoord.Width, mFontResource.FontGlyphInfo.LineSpace);

				// Quad texture
				RenderProgram.SetUniform(ctx, "ds_FontTextureOffset", glyphCoord.TexCoordOffsetX, glyphCoord.TexCoordOffsetY);
				RenderProgram.SetUniform(ctx, "ds_FontTextureScale", glyphCoord.TexQuadWidth, glyphCoord.TexQuadHeight);

				// Next glyph offset
				x += glyphCoord.Width;

				// Render as defined by RenderObject
				base.RenderThis(ctx);
			}
		}

		#endregion
	}
}
